package com.google.code.smon;

import com.google.code.smon.app.ServerMonitor;
import com.google.code.smon.app.StatusHandlerInstantiationException;
import com.google.code.smon.pers.Server;
import com.google.code.smon.pers.ServerStatus;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

/**
 * Hello world!
 *
 */
public class SMon {

    private static final String PERSISTENCE_UNIT_NAME = "smon";
    private static EntityManagerFactory factory;
    private Map<Server, ServerMonitor> serverList;
    private EntityManager em;
    private static Logger log = Logger.getLogger(SMon.class.getName());
    private Thread self;

    public SMon() {
        serverList = new HashMap<Server, ServerMonitor>();
        factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
        em = factory.createEntityManager();
        self = Thread.currentThread();
    }

    private void run() {

        while (!self.isInterrupted()) {
            try {
                synchronizeServers();
                Thread.sleep(10000);

            } catch (InterruptedException e) {
                break;
            }
        }

    }

    private void synchronizeServers() {
        int toDelete = 0, toAdd = 0;
        Query q = em.createQuery("select s from Server s");
        List<Server> newList = q.getResultList();


        /*
         * Fülle alle neuen Server von der DB in die serverList ein
         */
        for (Server s : newList) {

            if (!serverList.containsKey(s)) {
                if (s.getServerStatus() == null) {
                    ServerStatus st = new ServerStatus(s.getId());
                    st.setServiceStatus(false);
                    st.setLastChecked(new Date(0));
                    st.setLatency(0);
                }
                
                System.out.println("Processing " + s);
                ServerMonitor sm = creatServerMonitor(s);
                if (sm != null) {

                    serverList.put(s, sm);
                    //sm.start();
                    toAdd++;
                } else {
                    log.warning("Server " + s + " has been skipped due to previous error");
                }
            }
        }
        if (toAdd != 0) {
            log.info("Added " + toAdd + " new ServerMonitors");
        }
        /*
         * Lösche alle Server aus der serverList, die nicht mehr
         * in der DB sind und stoppe sie
         */
        for (Iterator<Server> it = serverList.keySet().iterator(); it.hasNext();) {
            Server s = it.next();
            if (!newList.contains(s)) {
                ServerMonitor sm = serverList.get(s);
                sm.interrupt();
                it.remove();
                toDelete++;
            }
        }
        if (toDelete != 0) {
            log.info("Deleted " + toDelete + " ServerMonitors");
        }
        log.fine("Refreshed serverlist");

    }

    private ServerMonitor creatServerMonitor(Server s) {
        ServerMonitor sm = null;

        try {
            sm = new ServerMonitor(s);
        } catch (StatusHandlerInstantiationException ex) {
            log.log(Level.SEVERE, ex.getMessage(), ex.getCause());
        }

        return sm;

    }

    public static void main(String[] args) throws Exception {
        LogSetup.setup();
        new SMon().run();
    }

    public void persist(Object object) {
        em.getTransaction().begin();
        try {
            em.persist(object);
            em.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
            em.getTransaction().rollback();
        } finally {
            em.close();
        }
    }
}
